import cv2
import os
from .utils_weice import *

def pad_line_max_grad(arr,avg_gray):
    set_gray = avg_gray * 0.55
    # 计算去除头尾10%数据的数量
    trim_length = int(arr.shape[1] * 0.1)
    
    # 对每一行进行排序
    sorted_rows = np.sort(arr, axis=1)
    
    # 去除头尾数据后计算平均值
    trimmed_rows = sorted_rows[:, trim_length:-trim_length]
    row_averages = np.mean(trimmed_rows, axis=1)
    
    #case 1 
    for i in range(len(row_averages)):
        if row_averages[i] < set_gray:
            row_averages[i] = 0
    # print("set_gray: ",set_gray)
    # print("row_averages: ",row_averages)
    
    # 计算相邻元素的差值
    row_differences = np.diff(row_averages, axis=0)
    # print("row_differences: ",row_differences)
    # 找到每行中差值的最大值
    # max_diff_per_row = np.max(row_differences, axis=0)
    # print("max_diff_per_row: ",max_diff_per_row)
    # 找到最大差值对应的行索引
    max_diff_row_index = np.argmax(row_differences, axis=0)
    
    #case2
    # i=0
    # while row_averages[max_diff_row_index] < set_gray :
    #     row_differences[max_diff_row_index] = 0
    #     max_diff_row_index = np.argmax(row_differences, axis=0)
        # i=i+1
        # if i>=10:
        #     break
    
    return max_diff_row_index,row_averages

def pad_refinement(image, pad_bbox, avg_gray,edge_offset=5, hw_ratio=0.1):
    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    x1, y1, x2, y2 = map(int, pad_bbox)
    w = x2 - x1
    h = y2 - y1
    h_offset = int((y2 - y1) * hw_ratio)
    w_offset = int((x2 - x1) * hw_ratio)
    
    #draw params
    if FLAG_DRAW_PAD_NUM:
        font = cv2.FONT_HERSHEY_SIMPLEX
        font_scale = 0.3
        font_color = (0, 0, 0)
        font_thickness = 1
        text_size = cv2.getTextSize("Sample Text", font, font_scale, font_thickness)[0]
        text_height = text_size[1]
        line_height = int(text_height * 1.5)
        half_index = 5
    # y1 上边
    crop_image = image_gray[y1-edge_offset: y1+edge_offset, x1+w_offset: x2-w_offset]
    y1_index,y1_list = pad_line_max_grad(crop_image,avg_gray)
    y1_refine = y1 - edge_offset + y1_index
    if FLAG_DRAW_PAD_NUM:
        first_half_y1 = y1_list[:half_index]
        second_half_y1 = y1_list[half_index:]
        result_first_y1 = ",".join([f"{int(y)}" for y in first_half_y1])
        result_second_y1 = ",".join([f"{int(y)}" for y in second_half_y1])
        cv2.putText(image, result_first_y1, (x1, y1-3), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
        cv2.putText(image, result_second_y1, (x1, y1+line_height), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
    
    # x2 右边
    crop_image = image_gray[y1+h_offset: y2-h_offset, x2-edge_offset:x2+edge_offset]
    crop_image = np.rot90(crop_image, k=1)
    # cv2.imshow('Image', crop_image)
    # cv2.waitKey(0)
    x2_index,x2_list = pad_line_max_grad(crop_image,avg_gray)
    x2_refine = x2 + edge_offset - x2_index
    if FLAG_DRAW_PAD_NUM:
        first_half_x2 = x2_list[:half_index]
        second_half_x2 = x2_list[half_index:]
        result_first_x2 = ",".join([f"{int(x)}" for x in first_half_x2])
        result_second_x2 = ",".join([f"{int(x)}" for x in second_half_x2])
        cv2.putText(image, result_first_x2, (x2-int(w/2), y1+int(h/2)), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
        cv2.putText(image, result_second_x2, (x2-int(w/2), y1+int(h/2)+line_height), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
   
    # y2 下边
    crop_image = image_gray[y2-edge_offset: y2+edge_offset, x1+w_offset: x2-w_offset]
    crop_image = np.rot90(crop_image, k=2)
    # cv2.imshow('Image', crop_image)
    # cv2.waitKey(0)
    y2_index,y2_list = pad_line_max_grad(crop_image,avg_gray)
    y2_refine = y2 + edge_offset - y2_index
    if FLAG_DRAW_PAD_NUM:
        first_half_y2 = y2_list[:half_index]
        second_half_y2 = y2_list[half_index:]
        result_first_y2 = ",".join([f"{int(y)}" for y in first_half_y2])
        result_second_y2 = ",".join([f"{int(y)}" for y in second_half_y2])
        cv2.putText(image, result_first_y2, (x1, y2-10), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
        cv2.putText(image, result_second_y2, (x1, y2-10+line_height), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
    
    # x1 左边
    crop_image = image_gray[y1+h_offset: y2-h_offset, x1-edge_offset:x1+edge_offset]
    crop_image = np.rot90(crop_image, k=-1)
    # cv2.imshow('Image', crop_image)
    # cv2.waitKey(0)
    x1_index,x1_list = pad_line_max_grad(crop_image,avg_gray)
    x1_refine = x1 - edge_offset + x1_index
    
    if FLAG_DRAW_PAD_NUM:
        first_half_x1 = x1_list[:half_index]
        second_half_x1 = x1_list[half_index:]
        result_first_x1 = ",".join([f"{int(x)}" for x in first_half_x1])
        result_second_x1 = ",".join([f"{int(x)}" for x in second_half_x1])
        cv2.putText(image, result_first_x1, (x1-int(w/2), y1+int(h/2)), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)
        cv2.putText(image, result_second_x1, (x1-int(w/2), y1+int(h/2)+line_height) , cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 0), 1)

    return [x1_refine, y1_refine, x2_refine, y2_refine]
    # return [x1, y1, x2, y2]

# 计算给定区域的平均灰度值
def calculate_average_gray(image, box):
    x1, y1, x2, y2 = int(box[0]), int(box[1]), int(box[2]), int(box[3])
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # print("gray_image: ", gray_image)
    # print(x1, y1, x2, y2)
    cropped_region = gray_image[y1:y2, x1:x2]
    # print("cropped_region: ", cropped_region)
    average_gray = np.mean(cropped_region)
    return average_gray


def cal_avg_pad_pixcal(image, pad_bbox, remove_box_list):
    # x1_1, y1_1, x2_1, y2_1 = pad_bbox
    # print("pad_box: ", x1_1, y1_1, x2_1, y2_1)
    cal_image = image.copy()    
    avg_gray = 0
    # print("pad_box: ", pad_bbox)
    crop_pixcal = 5
    for remove_box_info in remove_box_list:
        remove_box = remove_box_info[2]
        if check_intersection(pad_bbox, remove_box):
            x1_1, y1_1, x2_1, y2_1 = int(pad_bbox[0])+crop_pixcal, int(pad_bbox[1])+crop_pixcal, int(pad_bbox[2])-crop_pixcal, int(pad_bbox[3])-crop_pixcal
            x1_2, y1_2, x2_2, y2_2 = int(remove_box[0])+crop_pixcal, int(remove_box[1])+crop_pixcal, int(remove_box[2])-crop_pixcal, int(remove_box[3])-crop_pixcal
            # print("pad_box: ", x1_1, y1_1, x2_1, y2_1)
            # print("remove_box: ", x1_2, y1_2, x2_2, y2_2)
            
            # cv2.rectangle(cal_image, (x1_1, y1_1), (x2_1, y2_1), (0, 0, 255), 2)
            # cv2.rectangle(cal_image, (x1_2, y1_2), (x2_2, y2_2), (0, 255, 0), 2)
            # cv2.imwrite("picture.jpg", cal_image)
            
            intersection_x1 = max(x1_1, x1_2)
            intersection_y1 = max(y1_1, y1_2)
            intersection_x2 = min(x2_1, x2_2)
            intersection_y2 = min(y2_1, y2_2)   
       
            # print("intersection_box: ", intersection_x1, intersection_y1, intersection_x2, intersection_y2)  
            cal_image[intersection_y1:intersection_y2, intersection_x1:intersection_x2] = 0
 
        else:
            pass
    # cv2.imwrite("test.jpg", cal_image)
    # print("pad_box: ", pad_bbox)
    avg_gray = calculate_average_gray(cal_image, pad_bbox)  
    # print("avg_gray: ", avg_gray)
    # exit(0) 
    return avg_gray


def filter_edges_by_connectivity(edges, connectivity=8,min_line_length=20):
    ret,labels = cv2.connectedComponents(edges, connectivity=connectivity)  # connectivity表示连通域的连通类型，可选4或8，默认为8，上下左右和对角线八个方向
    unique_labels = np.unique(labels)
    component_sizes = [np.sum(labels == label) for label in unique_labels]

    min_size = min_line_length
    filtered_labels = [label for label, size in zip(unique_labels, component_sizes) if size >= min_size]
    #print(filtered_labels)

    conn = np.isin(labels, filtered_labels)
    edges_tobe_filtered = np.where(conn, 255, 0).astype(np.uint8)
    edges = cv2.bitwise_and(edges, edges_tobe_filtered)
    return edges


def pad_line(image,input_pad_list):
    fix_box_list = []
    for cur_pad in input_pad_list:
        cur_pad_box = cur_pad[2]
        cur_pad_box,_ = check_bbox_bounds(image, cur_pad_box)
        
        crop_pixcal = 10
        crop_box = [int(cur_pad_box[0])-crop_pixcal,int(cur_pad_box[1])-crop_pixcal,int(cur_pad_box[2])+crop_pixcal,int(cur_pad_box[3])+crop_pixcal]
        crop_box,_ = check_bbox_bounds(image, crop_box)
        image_pad = image[crop_box[1]:crop_box[3],crop_box[0]:crop_box[2]]
        
        # # 先灰度化，再高斯模糊，减小计算量
        # gray = cv2.cvtColor(image_pad,cv2.COLOR_BGR2GRAY)
        # gray = cv2.GaussianBlur(gray,(5,5),0)

        # # 计算灰度图的分位数，丢弃灰度值
        # q1,q2 = np.percentile(gray,[20,80])
        # gray = np.clip(gray,q1,q2).astype(np.uint8)

        # # 二值化
        # ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        # _,thresh = cv2.threshold(gray,ret*0.75,255,cv2.THRESH_BINARY)

        # # 边缘提取
        # kernel = np.ones((3,3),np.uint8)
        # thresh_2 = cv2.erode(thresh,kernel,iterations=1)
        # edges = cv2.Canny(thresh_2,ret*0.4,ret*0.8,apertureSize = 3,L2gradient=True)


        # # 连通性分析
        # edges = filter_edges_by_connectivity(edges,connectivity=8,min_line_length=(image_pad.shape[0]+image_pad.shape[1]))

        # # 闭运算 填充空洞，连接一些断开的部分
        # kernel = np.ones((3,3),np.uint8)
        # cross_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
        # ellipse_kernel_vertical = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
        # edges = cv2.morphologyEx(edges,cv2.MORPH_CLOSE,kernel)

        # # 寻找面积轮廓
        # contours,_ = cv2.findContours(edges,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        # if len(contours) == 0:
        #     continue
        # max_cnt = max(contours,key=cv2.contourArea)
        # x,y,w,h = cv2.boundingRect(max_cnt)
        # 先灰度化，再高斯模糊，减小计算量
        gray = cv2.cvtColor(image_pad,cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray,(3,3),0)

        # 计算灰度图的分位数，丢弃灰度值
        q1,q2 = np.percentile(gray,[20,82])
        gray = np.clip(gray,q1,q2).astype(np.uint8)

        # 二值化
        ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        _,thresh = cv2.threshold(gray,ret*0.78,255,cv2.THRESH_BINARY)

        # 边缘提取
        kernel = np.ones((3,3),np.uint8)
        thresh_2 = cv2.erode(thresh,kernel,iterations=1)
        edges = cv2.Canny(thresh_2,ret*0.4,ret*0.8,apertureSize=3,L2gradient=True)

        # 膨胀 腐蚀
        kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
        edges = cv2.morphologyEx(edges,cv2.MORPH_CLOSE,kernel)

        # 连通性分析
        edges = filter_edges_by_connectivity(edges,connectivity=8,min_line_length=(image_pad.shape[0]+image_pad.shape[1])*0.8)

        # 闭运算 填充空洞，连接一些断开的部分
        kernel = np.ones((3,3),np.uint8)
        #cross_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
        #ellipse_kernel_vertical = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
        edges = cv2.morphologyEx(edges,cv2.MORPH_CLOSE,kernel)

        # 寻找面积轮廓
        contours,_ = cv2.findContours(edges,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        if len(contours) == 0:
            fix_box_list.append(cur_pad_box)
            # print("contours is null")    
        else:
            max_cnt = max(contours,key=cv2.contourArea)
            x,y,w,h = cv2.boundingRect(max_cnt)
            # 对box多一层判断，异常时回退到模型预测结果
            if (x == 0 and y == 0) or (abs((w+h) - ((cur_pad_box[2]-cur_pad_box[0])+(cur_pad_box[3]-cur_pad_box[1]))) >= 0.35*max(image_pad.shape[0],image_pad.shape[1])):  
                print("回退到模型预测结果")
                fix_box_list.append(cur_pad_box)
            else:
                fix_box = [x+crop_box[0],y+crop_box[1],x+w+crop_box[0],y+h+crop_box[1]]
                fix_box_list.append(fix_box)
    return fix_box_list
        
        
    
    